#include "qrender/renderer.h"

#include <QOpenGLContext>
#include <QThread>
#include <QDebug>

#include <qrender/camera.h>

Renderer::Renderer()
{
}

void Renderer::requestCreate()
{
    if (!beginCreate()) {
        return;
    }

    create();
}

void Renderer::requestRender(const CameraInfo &camera_info)
{
    if (!visiable_ || !beginRender()) {
        return;
    }

    CameraInfo fixed_camera = camera_info;

    switch (fixed_) {
    case FixedType_FixedMatrix:
        fixed_camera.view_matrix = fixed_matrix_;
        break;
    case FixedType_FixedScale:
        fixed_camera.view_matrix.setColumn(3, QVector4D(fixed_scale_, 1));
        break;
    default:
        break;
    }

    render(fixed_camera);
}

void Renderer::requestRelease()
{
    if (!beginRelease()) {
        return;
    }

    release();
}

void Renderer::setVisible(bool visiable)
{
    visiable_ = visiable;
}

void Renderer::setFixed(bool fixed, const QMatrix4x4 &fixed_matrix)
{
    if (!fixed) {
        fixed_ = FixedType_Unfixed;
        return;
    }

    fixed_ = FixedType_FixedMatrix;
    fixed_matrix_ = fixed_matrix;
}

void Renderer::setFixed(bool fixed, const QVector3D &scale)
{
    if (!fixed) {
        fixed_ = FixedType_Unfixed;
        return;
    }

    fixed_ = FixedType_FixedScale;
    fixed_scale_ = scale;
}

bool Renderer::beginCreate()
{
    mtx_.lock();

    // 已创建且未发生变化, 则不重新创建
    if (thread_ == QThread::currentThread() &&
        ctx_ == QOpenGLContext::currentContext()) {
        qCritical()
            << "Renderer error: Created, please release before creating.";
        mtx_.unlock();
        return false;
    }

    thread_ = QThread::currentThread();
    ctx_ = QOpenGLContext::currentContext();

    mtx_.unlock();
    return true;
}

bool Renderer::beginRender()
{
    mtx_.lock();

    // 如果未创建数据，则先创建再渲染
    if (!thread_ && !ctx_) {
        mtx_.unlock();

        requestCreate();
        return true;
    }

    // 需要确保 create 与 render 函数在同一个线程及同一个上下文内执行
    if (thread_ != QThread::currentThread()) {
        qCritical() << "Renderer error: The function `init()` and `render()` "
                       "are not in the same thread!";
        mtx_.unlock();
        return false;
    }

    if (ctx_ != QOpenGLContext::currentContext()) {
        qCritical() << "Renderer error: The function `init()` and `render()` "
                       "are not in the same context!";
        mtx_.unlock();
        return false;
    }

    mtx_.unlock();
    return true;
}

bool Renderer::beginRelease()
{
    mtx_.lock();

    // 已被释放或未创建，则直接跳过
    if (!thread_ && !ctx_) {
        mtx_.unlock();
        return false;
    }

    // 需要确保 create 与 release 函数在同一个线程及同一个上下文内执行
    if (thread_ != QThread::currentThread()) {
        qCritical() << "Renderer error: The function `init()` and `release()` "
                       "are not in the same thread!";
        mtx_.unlock();
        return false;
    }

    if (ctx_ != QOpenGLContext::currentContext()) {
        qCritical() << "Renderer error: The function `init()` and `release()` "
                       "are not in the same context!";
        mtx_.unlock();
        return false;
    }

    ctx_ = nullptr;
    thread_ = nullptr;

    mtx_.unlock();
    return true;
}
